///////////////////////////////////////////////
//              实现标签页的切换              // 
///////////////////////////////////////////////

function initSwitchTab() {
    // 1. 获取相关元素(标签页按钮. 会话列表, 好友列表)
    let tabSession = document.querySelector('.tab .tab-session');
    let tabFriend = document.querySelector('.tab .tab-friend');
    let tabAddFriend = document.querySelector('.tab .tab-add-friend');
    let tabFriendReq = document.querySelector('.tab-friend-req');
    // querySelectorAll 可以同时选中多个元素, 得到的结果是个数组
    let lists = document.querySelectorAll('.list');
    // 2. 针对标签页按钮, 注册点击事件
    //    点击会话标签按钮, 就把会话标签按钮的背景图进行设置
    //    把会话列表显示出来, 好友卡列表隐藏
    //    点击好友按钮, 就把好友按钮背景图片重新设置
    //    显示好友列表, 隐藏会话列表

    // a) 设置图标
    tabSession.onclick = function () {
        tabSession.style.backgroundImage = 'url(img/对话1.png)';
        tabFriend.style.backgroundImage = 'url(img/用户2.png)';
        tabAddFriend.style.backgroundImage = 'url(img/搜索.png)';
        tabFriendReq.style.backgroundImage = 'url(img/添加用户2.png)';

        lists[0].classList = 'list';
        lists[1].classList = 'list hide';
        lists[2].classList = 'list hide';
        lists[3].classList = 'list hide';
    }

    tabFriend.onclick = function () {
        tabSession.style.backgroundImage = 'url(img/对话2.png)';
        tabFriend.style.backgroundImage = 'url(img/用户1.png)';
        tabAddFriend.style.backgroundImage = 'url(img/搜索.png)';
        tabFriendReq.style.backgroundImage = 'url(img/添加用户2.png)';

        lists[0].classList = 'list hide';
        lists[1].classList = 'list';
        lists[2].classList = 'list hide';
        lists[3].classList = 'list hide';
    }

    tabAddFriend.onclick = function () {
        tabSession.style.backgroundImage = 'url(img/对话2.png)';
        tabFriend.style.backgroundImage = 'url(img/用户2.png)';
        tabAddFriend.style.backgroundImage = 'url(img/搜索2.png)';
        tabFriendReq.style.backgroundImage = 'url(img/添加用户2.png)';

        lists[0].classList = 'list hide';
        lists[1].classList = 'list hide';
        lists[2].classList = 'list';
        lists[3].classList = 'list hide';
    }

    tabFriendReq.onclick = function () {
        tabSession.style.backgroundImage = 'url(img/对话2.png)';
        tabFriend.style.backgroundImage = 'url(img/用户2.png)';
        tabAddFriend.style.backgroundImage = 'url(img/搜索.png)';
        tabFriendReq.style.backgroundImage = 'url(img/添加用户1.png)';

        lists[0].classList = 'list hide';
        lists[1].classList = 'list hide';
        lists[2].classList = 'list hide';
        lists[3].classList = 'list';
    }
}

initSwitchTab();

///////////////////////////////////////////////
//              操作 webSocket               //
///////////////////////////////////////////////

// 创建 webSocket 实例
// let webSocket = new WebSocket('ws://localhost:8080/WebSocketMessage');
let webSocket = new WebSocket("ws://" + location.host + "/WebSocketMessage");


webSocket.onopen = function () {
    console.log("websocket 连接成功!");
}

webSocket.onclose = function () {
    console.log("websocket 连接断开!");
}

webSocket.onerror = function () {
    console.log("websocket 连接异常!");
}

webSocket.onmessage = function (e) {
    console.log("websocket 收到消息! " + e.data);
    // 此时收到的消息是一个 Json 格式的字符串, 需要转成 js 对象
    let resp = JSON.parse(e.data);
    if (resp.type === 'message') {
        // 处理消息响应
        handleMessage(resp);
    } else if (resp.type === 'friendRequest') {
        // 这是好友请求
        initFriendReq();
    } else if (resp.type === 'acceptFriendRequest') {
        // 对方接受好友请求
        // 刷新好友列表
        setTimeout('getFriendList();', 1000);
        console.log("flush friendList")
        // 清空搜索列表
        let addFriendUl = document.querySelector('#add-friend');
        addFriendUl.innerHTML = '';
        console.log("init search")
    } else {
        // resp 中的 type 出错
        console.log("resp.type 不符合要求")
    }
}

function handleMessage(resp) {
    // 把客户端收到的消息展示出来
    // 展示到对应的会话预览区域, 以及右侧的消息列表中

    // 1. 根据响应中的 sessionId 获取到当前的会话对应的 li 标签
    //    如果 li 标签不存在, 就创建一个新的
    let curSessionLi = findSessionLi(resp.sessionId);
    console.log("sessionId -> " + resp.sessionId);
    if (curSessionLi == null) {
        // 创建一个新的 li 标签. 表示新的会话
        curSessionLi = document.createElement('li');
        curSessionLi.setAttribute('message-session-id', resp.sessionId);
        // 此处 p 标签的内部应该放消息的预览内容, 此处置空, 第二步完成
        curSessionLi.innerHTML = '<h3>' + resp.fromName + '</h3>'
            + '<p></p>';
        // 给这个 li 标签也加上点击事件处理
        curSessionLi.onclick = function () {
            clickSession(curSessionLi);
        }
    }

    // 2. 把新的消息显示到会话的消息预览区域(li -> p)
    //    消息太长, 需要进行截断
    let p = curSessionLi.querySelector('p');
    p.innerHTML = resp.content;
    if (p.innerHTML.length > 10) {
        p.innerHTML = p.innerHTML.substring(0, 10) + '...';
    }

    // 3. 把收到消息的会话给放到会话列表的最上面
    let sessionListUl = document.querySelector('#session-list');
    sessionListUl.insertBefore(curSessionLi, sessionListUl.children[0]);

    // 4. 如果当前收到消息会话, 会话处于被选中状态, 就把消息放到右侧消息列表中
    //    新增消息的同时, 注意调整滚动条的位置, 保证消息在最底部, 让用户能直接看到
    if (curSessionLi.className === 'selected') {
        // 把消息列表添加一个新消息
        let messageShowDiv = document.querySelector('.right .message-show');
        addMessage(messageShowDiv, resp);
        scrollBottom(messageShowDiv);
    }

    // TODO: 其它操作: 可以在会话窗口上给个提示(红色数字, 几个消息未读), 可以播放提示音
}

function findSessionLi(targetSessionId) {
    // 获取到所有的会话列表中的 li 标签
    let sessionLis = document.querySelectorAll('#session-list li');
    for (let li of sessionLis) {
        let sessionId = li.getAttribute('message-session-id');
        // console.log("[findSessionLi] -> session ids -> " + sessionId);
        if (sessionId == targetSessionId) {
            return li;
        }
    }
    // 如果当前是一个新的一个用户给当前用户发消息, 此时没存在现成 li, 返回 null
    return null;
}

///////////////////////////////////////////////
//           实现消息发送和接收逻辑             //
///////////////////////////////////////////////

function initSendButton() {
    // 1. 获取到发送按钮 和 消息输入框
    let sendButton = document.querySelector('.right .ctrl button');
    let messageInput = document.querySelector('.right .message-input');
    // 2. 给发送按钮注册一个点击事件
    sendButton.onclick = function () {
        // a) 先给输入框的内容做一个简单判定. 比如输入框内容为空, 什么都不干
        if (!messageInput.value) {
            // value 的值是 null 或者是 '', 都会触发这个条件
            console.log("no message input");
            return;
        }
        // b) 获取当前选中的 li 标签 的 sessionId
        let selectedLi = document.querySelector('#session-list .selected');
        if (selectedLi == null) {
            // 当前没有 li 标签被选中
            return;
        }
        let sessionId = selectedLi.getAttribute('message-session-id');
        // c) 构造一个 json 数据
        let req = {
            type: 'message',
            sessionId: sessionId,
            content: messageInput.value
        };
        req = JSON.stringify(req);
        console.log("[webSocket] send: " + req);
        // d) 通过 webSocket 发送消息
        webSocket.send(req);
        // e) 消息发送之后, 清空当前的输入框
        messageInput.value = '';
    }
}

initSendButton();

///////////////////////////////////////////////
//         从服务器获取到用户登录数据           //
///////////////////////////////////////////////

function getUserInfo() {
    $.ajax({
        type: 'get',
        url: '/userInfo',
        success: function (body) {
            if (body.userId && body.userId > 0) {
                let userDiv = document.querySelector('.main .left .user');
                userDiv.innerHTML = body.username;
                userDiv.setAttribute("user-id", body.userId);
            } else {
                // 没登录, 跳到登录页面
                alert("当前用户未登录!");
                location.assign('login.html');
            }
        }
    });
}

getUserInfo();

// // 获取常态好友请求列表, 里面只有已发送当对方未接收的申请, 还有对方发来的申请
// function getAddFriendList() {
//     $.ajax({
//         type: 'get',
//         url: '/getAddFriendList',
//         success: function (body) {
//             // 清空当前列表
//             let addFriendUl = document.querySelector('#add-friend');
//             addFriendUl.innerHTML = '';
//
//             // 遍历 body, 将里面的元素添加进去
//             for (let request of body) {
//                 if (request.state == 1) {
//                     // 发起方
//                     addFriendUl.innerHTML += '<li><h4>' + request.username + '</h4><h3 style="color: #e74c3c">等待对方接受</h3></li>';
//                 } else {
//                     // 接收方
//                     addFriendUl.innerHTML += '<li><h4>' + request.username + '</h4>' +
//                         '<button class="custom-button toBeConfirmed" data-person="' + request.username + '">待确认</button>';
//                 }
//             }
//         }
//     });
// }
// getAddFriendList();

function getFriendList() {
    $.ajax({
        type: 'get',
        url: '/friendList',
        success: function (body) {
            // 清空好友列表
            let friendListUL = document.querySelector('#friend-list');
            friendListUL.innerHTML = '';

            // 遍历 body 把服务器响应的结果加到 当前的 friend-list 中
            for (let friend of body) {
                let li = document.createElement('li');
                li.innerHTML = '<h4>' + friend.friendName + '</h4>';
                // 此处把 friendId 记录下来, 以备后用
                li.setAttribute('friend-id', friend.friendId);
                friendListUL.appendChild(li);

                // 每个 li 标签, 就对应界面上的一个好友选项, 给这个 li 加上点击事件的处理
                li.onclick = function () {
                    // 参数区分了当前用户点击的是哪个好友
                    clickFriend(friend);
                }
            }
        },
        error: function () {
            console.log('获取好友 列表失败!');
        }
    });
}

getFriendList();

function getSessionList() {
    $.ajax({
        type: 'get',
        url: '/sessionList',
        success: function (body) {
            // 1. 清空原来的会话列表
            let sessionListUL = document.querySelector('#session-list');
            sessionListUL.innerHTML = '';

            // 2. 遍历响应数组, 针对结果来构造页面
            for (let session of body) {
                // 针对 lastMessage 的长度进行截断处理
                if (session.lastMessage.length > 10) {
                    session.lastMessage = session.lastMessage.substring(0, 10) + '...';
                }
                let li = document.createElement('li');
                // 保存会话 Id 到 li 标签的属性这中
                li.setAttribute('message-session-id', session.sessionId);
                li.innerHTML = '<h3>' + session.friends[0].friendName + '<h3>' +
                    '<p>' + session.lastMessage + '</p>';
                sessionListUL.appendChild(li);

                // 给 li 标签新增一个点击事件
                li.onclick = function () {
                    // 这个写法就能保证点击哪个 li 标签, clickSession() 就能拿到哪个 li 标签
                    clickSession(li);
                }
            }
        }
    });
}

getSessionList();

function clickSession(currentLi) {
    // 1. 设置高亮状态 (active)
    let allLis = document.querySelectorAll('#session-list>li');
    activeSession(allLis, currentLi);
    // 2. 获取指定会话的历史消息
    let sessionId = currentLi.getAttribute("message-session-id");
    getHistoryMessage(sessionId);
}

function activeSession(allLis, currentLi) {
    for (let li of allLis) {
        if (li === currentLi) {
            li.className = 'selected';
        } else {
            li.className = '';
        }
    }
}

// 这个函数获取指定会话的历史消息
function getHistoryMessage(sessionId) {
    console.log("获取历史消息 sessionId = " + sessionId);
    // 1. 清空右侧列表的已有内容
    let titleDiv = document.querySelector('.right .title');
    titleDiv.innerHTML = '';
    let messageShowDiv = document.querySelector('.right .message-show');
    messageShowDiv.innerHTML = '';

    // 2. 重新设置一下会话的消息, 新的会话的标题是点击的那个会话上显示的标题
    //    先找到当前选中的会话是那个, 被选中的会话是带有 selected 类的
    let selectedH3 = document.querySelector('#session-list .selected>h3');
    if (selectedH3) {
        // selectedH3 可能不存在, 在页面加载阶段, 并没有哪个会话被选中,
        // 就没有 selected 标签, 此时就无法查询到这个 selectedH3 标签了
        titleDiv.innerHTML = selectedH3.innerHTML;
    }

    // 3. 发送一个 ajax 请求, 获取指定会话的历史消息
    $.ajax({
        type: 'get',
        url: '/message?sessionId=' + sessionId,
        success: function (body) {
            // 此处返回的 body 是个 js 对象数组, 里面的每一个元素都是一条消息
            for (let message of body) {
                addMessage(messageShowDiv, message);
            }
            // 加个操作, 获取完消息信息之后, 控制滚动条滚动到最下面
            scrollBottom(messageShowDiv);
        }
    });
}

function addMessage(messageShowDiv, message) {
    // 使用这个 div 表示一条消息
    let messageDiv = document.createElement('div');
    // 此处需要针对当前消息是不是用户自己发的吗决定是靠左还是靠右
    let selfUserName = document.querySelector('.left .user').innerHTML;
    if (selfUserName === message.fromName) {
        // 消息是自己发的, 靠右
        messageDiv.className = 'message message-right';
    } else {
        // 消息是别人发的, 靠左
        messageDiv.className = 'message message-left';
    }
    messageDiv.innerHTML = '<div class="box">'
        + '<h4>' + message.fromName + '</h4>'
        + '<p>' + message.content + '</p>'
        + '</div>';
    messageShowDiv.appendChild(messageDiv);
}

// 把 messageDiv 里面的内容滚动到最底部
function scrollBottom(elem) {
    // 1. 获取到可视距离的高度
    let clientHeight = elem.offsetHeight;
    // 2. 获取到总内容的高度
    let scrollHeight = elem.scrollHeight;
    // 3. 进行滚动操作, 第一个参数是水平滚动的尺寸, 第二个参数是垂直滚动的尺寸
    elem.scroll(0, scrollHeight - clientHeight);
}

// 点击好友列表项触发的函数
function clickFriend(friend) {
    // 1. 判定一下当前的好友有没有对应的会话
    // 使用一个单独的函数来实现, 这个函数的参数是用户的名字, 返回值是以一个 li 标签
    // 找到了就返回会话列表中对应的 li, 没找到, 返回 null.
    let sessionLi = findSessionByName(friend.friendName);
    let sessionListUL = document.querySelector('#session-list');
    if (sessionLi) {
        // 2. 如果当前存在匹配的结果, 就把会话设置成选中状态, 获取历史消息, 并且置顶
        //      insertBefore 把这个找到的 li 标签放到最前面去
        sessionListUL.insertBefore(sessionLi, sessionListUL.children[0]);
        // 此处设置会话的选中状态以及获取历史消息这两个功能在上面的 clickSession 中已经实现
        // clickSession(sessionLi);
        // 或者模拟点击
        sessionLi.click();
    } else {
        // 3. 如果不存在匹配的结果, 就创建个新会话(创建 li 标签 + 通知服务器)
        sessionLi = document.createElement('li');
        // 构造具体的 li 标签内容, 由于新会话中没有最后一条消息, 所以 p 标签就置空
        sessionLi.innerHTML = '<h3>' + friend.friendName + '</h3>' + '<p></p>';
        // 把标签进行置顶
        sessionListUL.insertBefore(sessionLi, sessionListUL.children[0]);
        sessionLi.onclick = function () {
            clickSession(sessionLi);
        }
        sessionLi.click();
        // 发送消息给服务器, 告诉服务器说当前新创建的会话是啥样的
        createSession(friend.friendId, sessionLi);
    }

    // 4. 还需要把标签页切换到 会话列表
    // 只要找到会话列表标签页按钮, 模拟一个点击操作就行
    let tabSession = document.querySelector('.tab .tab-session');
    tabSession.click();
}

function findSessionByName(username) {
    // 先获取到会话列表中的所有的 li 标签
    // 依次遍历, 看看这些 li 标签谁的名字和要查找的一致.
    let sessionLis = document.querySelectorAll('#session-list>li');
    for (let li of sessionLis) {
        // 获取到该 li 标签里的 h3 标签, 进一步得到名字
        let h3 = li.querySelector('h3');
        if (h3.innerHTML === username) {
            return li;
        }
    }
    return null;
}

// friendId 是构造 HTTP 请求时必要的信息
function createSession(friendId, sessionLi) {
    $.ajax({
        type: 'post',
        url: '/session?toUserId=' + friendId,
        success: function (body) {
            console.log("会话创建成功, sessionId = " + body.sessionId);
            sessionLi.setAttribute('message-session-id', body.sessionId);
        },
        error: function () {
            console.log("会话创建失败!");
        }
    });
}


///////////////////////////////////////////////
//                 回车事件                   //
///////////////////////////////////////////////

// 1. 搜索用户
$(document).ready(function () {
    $(".search input").keydown(function (event) {
        if (event.keyCode == 13) {
            let searchButton = document.querySelector('.search button');
            searchButton.click();
        }
    });
});


// 2. 发送消息
$(document).ready(function () {
    $(".right textarea").keydown(function (event) {
        if (event.keyCode == 13) {
            let sendMessageButton = document.querySelector('.right .ctrl button');
            sendMessageButton.click();
        }
    });
});


///////////////////////////////////////////////
//               点击添加好友                 //
///////////////////////////////////////////////
$(document).ready(function () {
    // 点击"添加好友"按钮，显示模态框
    function dialogBox() {
        // 获取相关元素
        let closeModalBtn = $("#cancelBtn");
        let addFriendBtn = $("#addFriendBtn");
        let modal = $("#myModal");
        let personName = $("#personName");


        $(".custom-button").on("click", function () {
            modal.css("display", "block");
            personName.text($(this).data("person")); // 在模态框中显示对应的人的名字
        });


        // 点击"关闭"按钮或模态框外部区域，关闭模态框
        closeModalBtn.on("click", function () {
            modal.css("display", "none");
        });

        modal.on("click", function (event) {
            if (event.target === modal[0]) {
                modal.css("display", "none");
            }
        });

        // 点击"添加"按钮时的逻辑
        addFriendBtn.on("click", function () {
            let reasonInput = $("#reasonInput").val();
            const person = personName.text();
            // 在这里可以将添加好友的理由提交处理
            console.log("添加好友的理由：" + reasonInput);
            console.log("要添加的对象：" + person);
            modal.css("display", "none"); // 关闭模态框
            // 发送好友申请
            sendFriendRequest(reasonInput, person);

            // 构造添加好友请求给 websocket
            let req = {
                type: 'friendRequest',
                receiver: person
            }
            req = JSON.stringify(req);
            console.log("[webSocket] send: " + req);
            webSocket.send(req);
        });
    }

    // 发起好友请求
    function sendFriendRequest(reasonInput, receiver) {
        $.ajax({
            type: "post",
            url: "/sendFriendReq",
            data: {
                message: reasonInput,
                receiverName: receiver
            },
            success: function (body) {
                // 模拟鼠标点击搜索按钮, 再次刷新搜索列表, 与数据库同步
                searchButton.click();
            }
        });
    }

    // 点击搜索按钮, 通过用户名查找用户
    let searchButton = $("div.search > button");
    searchButton.on("click", function () {
        // 获取搜索框中的文字
        let username = $("#inputBox").val();
        console.log(username);
        // 构造 ajax 请求来获取查找到的用户
        $.ajax({
            type: "get",
            url: "/searchUser?searchElement=" + username,
            success: function (body) {
                // 切换标签页到添加好友 (模拟点击)
                let addFriendDiv = $(".tab-add-friend");
                addFriendDiv.click();
                // 清空 ul 标签中的所有元素
                let addFriendUl = $("#add-friend");
                addFriendUl.empty();
                // 拼接搜索出来的用户, 如果已经添加或者已经发送好友请求了就不显示添加好友按钮
                for (let user of body) {
                    if (user.state == 1) {
                        // 发起方
                        addFriendUl.append(
                            '<li><h4>' +
                            user.username +
                            '</h4><h3 style="color: #e74c3c">等待对方接受</h3></li>'
                        );
                    } else if (user.state == 2) {
                        // 未添加好友
                        addFriendUl.append(
                            '<li><h4>' +
                            user.username +
                            '</h4><button class="custom-button" data-person="' +
                            user.username +
                            '">添加好友</button></li>'
                        );
                    } else if (user.state == 3) {
                        // 已添加好友
                        addFriendUl.append(
                            '<li><h4>' +
                            user.username +
                            '</h4><h3 style="color: #3de723">已添加好友</h3>'
                        );
                    }
                }
                // 获取所有"添加好友"按钮并传入dialogBox函数
                const openModalBtns = $(".custom-button");
                // 移除$(".custom-button")上的点击事件绑定
                $(".custom-button").off("click");

                dialogBox(openModalBtns);
                // dialogBox();
            }
        });
    })

    // // 初始化，为所有按钮添加点击事件监听器
    // const openModalBtns = $(".custom-button");
    // dialogBox(openModalBtns);
});


///////////////////////////////////////////////
//                 好友请求                   //
///////////////////////////////////////////////


// 初始化好友请求
function initFriendReq() {
    // 获取请求信息
    $.ajax({
        type: 'get',
        url: '/getFriendReq',
        success: function (body) {
            // 获取到对应的列表
            let reqUl = document.querySelector("#friend-req");
            // 清空当前列表
            reqUl.innerHTML = '';
            // 往里面拼接元素
            for (let req of body) {
                reqUl.innerHTML += '<li>\n' +
                    '                    <div class="friend-req-item">\n' +
                    '                        <h4 class="name">' + req.username + ' -> 申请</h4>\n' +
                    '                        <p class="message">验证消息: ' + req.message + '</p>\n' +
                    '                        <div class="buttons">\n' +
                    '                            <button class="accept-btn" data-req-id="' + req.userId + '">接受</button>\n' +
                    '                            <button class="reject-btn" data-req-id="' + req.userId + '">拒绝</button>\n' +
                    '                        </div>\n' +
                    '                    </div>\n' +
                    '                </li>';
            }
            // 注册点击事件
            buttonOnclickReg();
        }
    });
}

initFriendReq();

function buttonOnclickReg() {
    // 点击拒绝按钮
    // 获取按钮
    let rejectButtons = document.querySelectorAll('.reject-btn');
    // 添加点击事件处理程序
    rejectButtons.forEach(button => {
        button.addEventListener('click', () => {
            // 获取好友请求的标识
            const requestId = button.getAttribute('data-req-id');

            // 找到对应的<li>元素
            const listItem = button.closest('li');

            console.log(listItem + " 点击了拒绝按钮");

            // 在这里根据requestId来处理对应的好友请求
            $.ajax({
                type: 'post',
                url: '/rejectFriendReq',
                data: {
                    requestId: requestId
                },
                success: function (body) {
                    // 删除这个请求
                    listItem.remove();
                }
            });
            console.log(`已拒绝好友请求：${requestId}`);
        });
    });

// 点击接受按钮
// 获取按钮
    let acceptButtons = document.querySelectorAll('.accept-btn');
    acceptButtons.forEach(button => {
        button.addEventListener('click', () => {
            // 获取好友请求的标识
            const requestId = button.getAttribute('data-req-id');
            // 找到对应的<li>元素
            const listItem = button.closest('li');

            // 构建 webSocket 请求
            let req = {
                type: 'acceptFriendRequest',
                requestId: requestId
            }
            req = JSON.stringify(req);
            console.log("[webSocket] send: " + req);
            webSocket.send(req);

            console.log(listItem + " 点击了接受按钮");
            $.ajax({
                type: 'post',
                url: '/acceptFriendReq',
                data: {
                    requestId: requestId
                },
                success: function (body) {
                    // 删除这个请求
                    listItem.remove();
                    // 好友列表刷新
                    getFriendList();
                }
            });
            console.log(`已接受好友请求：${requestId}`);
        });
    });
}


